using System;
using System.Collections.Generic;
using System.Linq;
using WenYu.Core.Errors;

namespace WenYu.Core.CodeGen
{
    /// <summary>
    /// 符号表 - 管理变量的类型、作用域和索引
    /// 
    /// 功能:
    /// - 变量声明: 记录变量名、类型、索引
    /// - 变量查询: 检查变量是否存在、获取类型
    /// - 作用域管理: 支持嵌套作用域（为Phase 2+预留）
    /// 
    /// 对标需求: REQ-04 代码生成器
    /// </summary>
    public class SymbolTable
    {
        /// <summary>变量信息</summary>
        public class VariableInfo
        {
            /// <summary>变量名</summary>
            public string Name { get; set; }
            
            /// <summary>类型（整型、实型、文字等）</summary>
            public string Type { get; set; }
            
            /// <summary>变量在栈/内存中的索引</summary>
            public int Index { get; set; }
            
            /// <summary>作用域深度</summary>
            public int ScopeDepth { get; set; }
        }
        
        /// <summary>函数信息</summary>
        public class FunctionInfo
        {
            /// <summary>函数名</summary>
            public string Name { get; set; }
            
            /// <summary>返回类型（null表示无返回值）</summary>
            public string? ReturnType { get; set; }
            
            /// <summary>参数类型列表</summary>
            public List<string> ParameterTypes { get; set; } = new();
            
            /// <summary>函数入口地址（指令索引）</summary>
            public int EntryAddress { get; set; }
            
            /// <summary>参数个数</summary>
            public int ParameterCount => ParameterTypes.Count;
        }
        
        /// <summary>类信息</summary>
        public class ClassInfo
        {
            /// <summary>类名</summary>
            public string Name { get; set; }
            
            /// <summary>字段信息：字段名 -> 字段类型</summary>
            public Dictionary<string, string> Fields { get; set; } = new();
            
            /// <summary>字段默认值：字段名 -> 默认值</summary>
            public Dictionary<string, object?> FieldDefaults { get; set; } = new();
            
            /// <summary>成员函数信息：方法名 -> FunctionInfo</summary>
            public Dictionary<string, FunctionInfo> Methods { get; set; } = new();
        }
        
        /// <summary>全局变量表</summary>
        private readonly Dictionary<string, VariableInfo> _variables = new();
        
        /// <summary>函数表</summary>
        private readonly Dictionary<string, FunctionInfo> _functions = new();
        
        /// <summary>类表</summary>
        private readonly Dictionary<string, ClassInfo> _classes = new();
        
        /// <summary>标准库函数注册表</summary>
        private StandardLibraryRegistry? _stdLibRegistry;
        
        /// <summary>当前作用域深度</summary>
        private int _scopeDepth = 0;
        
        /// <summary>变量计数器（用于分配索引）</summary>
        private int _varCounter = 0;
        
        // ===== 标准库函数管理 =====
        
        /// <summary>
        /// 注册标准库（在CodeGenerator初始化时调用）
        /// </summary>
        public void RegisterStandardLibrary(StandardLibraryRegistry registry)
        {
            _stdLibRegistry = registry;
        }
        
        /// <summary>
        /// 检查函数是否存在（包括用户函数和标准库函数）
        /// </summary>
        public bool HasFunction(string name)
        {
            // 先检查用户定义的函数
            if (_functions.ContainsKey(name))
                return true;
            
            // 再检查标准库函数
            if (_stdLibRegistry != null && _stdLibRegistry.HasFunction(name))
                return true;
            
            return false;
        }
        
        /// <summary>
        /// 检查是否为标准库函数
        /// </summary>
        public bool IsStandardLibraryFunction(string name)
        {
            return _stdLibRegistry != null && _stdLibRegistry.HasFunction(name);
        }
        
        /// <summary>
        /// 获取标准库函数信息
        /// </summary>
        public StandardLibraryFunctionInfo? GetStandardLibraryFunction(string name)
        {
            if (_stdLibRegistry == null)
                return null;
            
            return _stdLibRegistry.TryGetFunction(name, out var funcInfo) ? funcInfo : null;
        }
        
        /// <summary>
        /// 验证函数调用（包括参数检查）
        /// </summary>
        public bool ValidateFunctionCall(string name, int argCount, out string? errorMessage)
        {
            errorMessage = null;
            
            // 用户定义的函数
            if (_functions.TryGetValue(name, out var userFunc))
            {
                if (argCount != userFunc.ParameterCount)
                {
                    errorMessage = $"函数 '{name}' 期望 {userFunc.ParameterCount} 个参数，实际提供了 {argCount} 个";
                    return false;
                }
                return true;
            }
            
            // 标准库函数
            if (_stdLibRegistry != null)
            {
                return _stdLibRegistry.ValidateArguments(name, argCount, out errorMessage);
            }
            
            errorMessage = $"未定义的函数: {name}";
            return false;
        }
        
        // ===== 变量管理 =====
        
        /// <summary>定义新变量</summary>
        /// <exception cref="InvalidOperationException">变量已定义</exception>
        public void DefineVariable(string name, string type, int line = 0, int column = 0, string sourceCode = "")
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentException("变量名不能为空", nameof(name));
            
            if (string.IsNullOrEmpty(type))
                throw new ArgumentException("变量类型不能为空", nameof(type));
            
            // MVP中: 检查全局重定义
            if (_variables.ContainsKey(name))
            {
                var firstDefined = _variables[name];
                var error = CodeGenErrors.DuplicateVariable(
                    name, 
                    line, 
                    column, 
                    sourceCode,
                    firstDefined.Index // 使用Index作为首次定义的近似行号
                );
                new ConsoleErrorFormatter().Print(error);
                throw new CodeGenException(error);
            }
            
            _variables[name] = new VariableInfo
            {
                Name = name,
                Type = type,
                Index = _varCounter++,
                ScopeDepth = _scopeDepth
            };
        }
        
        /// <summary>获取变量信息</summary>
        /// <exception cref="CodeGenException">变量不存在</exception>
        public VariableInfo GetVariable(string name, int line = 0, int column = 0, string sourceCode = "")
        {
            if (!_variables.TryGetValue(name, out var info))
            {
                // 获取所有可用变量名
                var availableVars = _variables.Keys.ToList();
                
                var error = CodeGenErrors.UndefinedVariable(
                    name, 
                    line, 
                    column, 
                    sourceCode,
                    availableVars
                );
                new ConsoleErrorFormatter().Print(error);
                throw new CodeGenException(error);
            }
            return info;
        }
        
        /// <summary>检查变量是否存在</summary>
        public bool HasVariable(string name)
        {
            return _variables.ContainsKey(name);
        }
        
        /// <summary>移除变量（用于清理函数参数等临时变量）</summary>
        public void RemoveVariable(string name)
        {
            _variables.Remove(name);
        }
        
        /// <summary>获取变量类型</summary>
        public string GetVariableType(string name)
        {
            return GetVariable(name).Type;
        }
        
        /// <summary>获取变量索引</summary>
        public int GetVariableIndex(string name)
        {
            return GetVariable(name).Index;
        }
        
        /// <summary>进入新作用域（为Phase 2+预留）</summary>
        public void PushScope()
        {
            _scopeDepth++;
        }
        
        /// <summary>退出作用域（为Phase 2+预留）</summary>
        public void PopScope()
        {
            if (_scopeDepth > 0)
            {
                // 移除该作用域内的所有变量
                var keysToRemove = new List<string>();
                foreach (var kvp in _variables)
                {
                    if (kvp.Value.ScopeDepth == _scopeDepth)
                        keysToRemove.Add(kvp.Key);
                }
                
                foreach (var key in keysToRemove)
                    _variables.Remove(key);
                
                _scopeDepth--;
            }
        }
        
        /// <summary>获取所有变量</summary>
        public IReadOnlyDictionary<string, VariableInfo> GetAllVariables()
        {
            return _variables;
        }
        
        /// <summary>获取变量总数</summary>
        public int VariableCount => _varCounter;
        
        // ===== 函数管理 =====
        
        /// <summary>定义新函数</summary>
        /// <exception cref="InvalidOperationException">函数已定义</exception>
        public void DefineFunction(string name, string? returnType, List<string> parameterTypes, int entryAddress)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentException("函数名不能为空", nameof(name));
            
            if (_functions.ContainsKey(name))
                throw new InvalidOperationException($"函数 '{name}' 已定义");
            
            _functions[name] = new FunctionInfo
            {
                Name = name,
                ReturnType = returnType,
                ParameterTypes = parameterTypes ?? new List<string>(),
                EntryAddress = entryAddress
            };
        }
        
        /// <summary>获取函数信息</summary>
        /// <exception cref="KeyNotFoundException">函数不存在</exception>
        public FunctionInfo GetFunction(string name)
        {
            if (!_functions.TryGetValue(name, out var info))
                throw new KeyNotFoundException($"未定义的函数: {name}");
            return info;
        }
        
        /// <summary>获取函数入口地址</summary>
        public int GetFunctionAddress(string name)
        {
            return GetFunction(name).EntryAddress;
        }
        
        /// <summary>获取函数总数</summary>
        public int FunctionCount => _functions.Count;
        
        // ===== 类管理 =====
        
        /// <summary>定义新类</summary>
        /// <exception cref="InvalidOperationException">类已定义</exception>
        public void DefineClass(string name, Dictionary<string, string> fields, Dictionary<string, object?> fieldDefaults, Dictionary<string, FunctionInfo> methods)
        {
            if (string.IsNullOrEmpty(name))
                throw new ArgumentException("类名不能为空", nameof(name));
            
            if (_classes.ContainsKey(name))
                throw new InvalidOperationException($"类 '{name}' 已定义");
            
            _classes[name] = new ClassInfo
            {
                Name = name,
                Fields = fields ?? new Dictionary<string, string>(),
                FieldDefaults = fieldDefaults ?? new Dictionary<string, object?>(),
                Methods = methods ?? new Dictionary<string, FunctionInfo>()
            };
        }
        
        /// <summary>获取类信息</summary>
        /// <exception cref="KeyNotFoundException">类不存在</exception>
        public ClassInfo GetClass(string name)
        {
            if (!_classes.TryGetValue(name, out var info))
                throw new KeyNotFoundException($"未定义的类: {name}");
            return info;
        }
        
        /// <summary>检查类是否存在</summary>
        public bool HasClass(string name)
        {
            return _classes.ContainsKey(name);
        }
        
        /// <summary>获取类的字段类型</summary>
        public string GetClassFieldType(string className, string fieldName)
        {
            var classInfo = GetClass(className);
            if (!classInfo.Fields.TryGetValue(fieldName, out var fieldType))
                throw new KeyNotFoundException($"类 '{className}' 中未定义字段 '{fieldName}'");
            return fieldType;
        }
        
        /// <summary>检查类是否有指定字段</summary>
        public bool ClassHasField(string className, string fieldName)
        {
            if (!HasClass(className)) return false;
            return GetClass(className).Fields.ContainsKey(fieldName);
        }
        
        /// <summary>检查类是否有指定方法</summary>
        public bool ClassHasMethod(string className, string methodName)
        {
            if (!HasClass(className)) return false;
            return GetClass(className).Methods.ContainsKey(methodName);
        }
        
        /// <summary>获取类的方法信息</summary>
        public FunctionInfo GetClassMethod(string className, string methodName)
        {
            var classInfo = GetClass(className);
            if (!classInfo.Methods.TryGetValue(methodName, out var methodInfo))
                throw new KeyNotFoundException($"类 '{className}' 中未定义方法 '{methodName}'");
            return methodInfo;
        }
        
        /// <summary>获取类总数</summary>
        public int ClassCount => _classes.Count;
        
        /// <summary>清空符号表</summary>
        public void Clear()
        {
            _variables.Clear();
            _functions.Clear();
            _classes.Clear();
            _varCounter = 0;
            _scopeDepth = 0;
        }
        
        /// <summary>调试输出</summary>
        public override string ToString()
        {
            return $"SymbolTable: {_variables.Count} variables, {_functions.Count} functions, {_classes.Count} classes, Scope Depth: {_scopeDepth}";
        }
    }
}
